﻿#include "CrossEQItem.h"
#include "CrossEQ.h"
#include <QPainter>
#include <QDebug>
#include <QCursor>
#include <QApplication>
#include <QDesktopWidget>
#include <QPainterPath>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneHoverEvent>

namespace GeneralUI {

	CrossEQItem::CrossEQItem(QObject *parent)
		: m_parentObj(parent)
		, m_isScreenMap(false)
		, m_isEnabled(true)
		, m_xMinValue(-1024)
		, m_yMinValue(-1024)
		, m_xMaxValue(1024)
		, m_yMaxValue(1024)
		, m_lastValueX(-1)
		, m_lastValueY(-1)
		, m_width(132)
		, m_height(132)
		, m_centerBlockSize(16)
		, m_pixStep(1)
		, m_moveMode(None)
		, m_decimals(0)
		, m_multiple(1)
	{
		setFlag(QGraphicsItem::ItemIsFocusable);
		init();
	}

	CrossEQItem::~CrossEQItem()
	{

	}

	void CrossEQItem::setItemSize(int width, int height)
	{
		m_width = width - 1;
		m_height = height - 1;
		m_centerPoint = QPointF(m_width / 2, m_height / 2);

		prepareGeometryChange();
		updateUI();
	}

	void CrossEQItem::setValue(double valueX, double valueY)
	{
		valueX *= m_multiple;
		valueY *= m_multiple;
		m_valueX = qBound(m_xMinValue, valueX, m_xMaxValue);
		m_valueY = qBound(m_yMinValue, valueY, m_yMaxValue);
		double xPix = (m_valueX - m_xMinValue) * m_width * 1.f / (m_xMaxValue - m_xMinValue);
		double yPix = m_height - (m_valueY - m_yMinValue) * m_height * 1.f / (m_yMaxValue - m_yMinValue);

		m_centerPoint = QPointF(xPix, yPix);
		notifyValueChange();

		updateUI();
	}

	QPointF CrossEQItem::getValue()
	{
		double valueX = m_valueX / m_multiple;
		double valueY = m_valueY / m_multiple;
		return QPointF(valueX, valueY);
	}

	void CrossEQItem::setDecimals(int decs)
	{
		if (decs < 0)
		{
			return;
		}
		m_decimals = decs;
		initForm(pow(10, m_decimals));
	}

	void CrossEQItem::setMinValue(int minValue)
	{
		m_xMinValue = minValue * m_multiple;
		m_yMinValue = minValue * m_multiple;
	}

	void CrossEQItem::setMaxValue(int maxValue)
	{
		m_xMaxValue = maxValue * m_multiple;
		m_yMaxValue = maxValue * m_multiple;
	}

	void CrossEQItem::setRange(int minValue, int maxValue)
	{
		m_xMinValue = minValue * m_multiple;
		m_yMinValue = minValue * m_multiple;
		m_xMaxValue = maxValue * m_multiple;
		m_yMaxValue = maxValue * m_multiple;
	}

	void CrossEQItem::setRange(int xMin, int xMax, int yMin, int yMax)
	{
		m_xMinValue = xMin * m_multiple;
		m_yMinValue = yMin * m_multiple;
		m_xMaxValue = xMax * m_multiple;
		m_yMaxValue = yMax * m_multiple;
	}

	void CrossEQItem::setPixStep(double step)
	{
		if (step < 1e-02)
		{
			step = 1e-02;
		}
		//m_pixStep = step / m_multiple;
	}

	void CrossEQItem::setEnabled(bool isEnable)
	{
		m_isEnabled = isEnable;
		updateUI();
	}

	bool CrossEQItem::hasFocus() const
	{
		return m_moveMode != None;
	}

	void CrossEQItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /*= nullptr*/)
	{
		Q_UNUSED(option)
			Q_UNUSED(widget)

			if (m_isEnabled)
			{
				painter->setPen(QPen(QColor(36, 83, 164), 1));
			}
			else
			{
				painter->setPen(QPen(QColor(198, 198, 198), 1));
			}
		painter->drawPath(m_centerPath);
		// 上
		painter->drawLine(QPointF(m_centerPoint.rx(), m_centerPoint.ry() - m_centerBlockSize / 2),
			QPointF(m_centerPoint.rx(), -1));

		// 下
		painter->drawLine(QPointF(m_centerPoint.rx(), m_centerPoint.ry() + m_centerBlockSize / 2),
			QPointF(m_centerPoint.rx(), m_height + 1));

		// 左
		painter->drawLine(QPointF(m_centerPoint.rx() - m_centerBlockSize / 2, m_centerPoint.ry()),
			QPointF(-1, m_centerPoint.ry()));

		// 右
		painter->drawLine(QPointF(m_centerPoint.rx() + m_centerBlockSize / 2, m_centerPoint.ry()),
			QPointF(m_width + 1, m_centerPoint.ry()));
	}

	void CrossEQItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
	{
		if (!m_isEnabled)
		{
			setCursor(Qt::ForbiddenCursor);
			return;
		}

		QPointF point = event->pos();
		if (m_centerPath.contains(point))
		{
			setCursor(Qt::SizeAllCursor);
		}
		else if (m_horPath.contains(point))
		{
			setCursor(Qt::SizeVerCursor);
		}
		else if (m_verPath.contains(point))
		{
			setCursor(Qt::SizeHorCursor);
		}
		else
		{
			setCursor(Qt::ArrowCursor);
		}
	}

	void CrossEQItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
	{
		QPointF point, curPoint;
		if (m_isScreenMap)
		{
			point = event->screenPos();
			curPoint = event->screenPos();
			point.setX(qBound(0.0, point.x() + 2, (double)m_screenRect.width() + 1));
			point.setY(qBound(0.0, point.y() + 2, (double)m_screenRect.height() + 1));
		}
		else
		{
			point = event->pos();
			curPoint = event->pos();
			double pixOffset = m_width * m_pixStep / 2;
		}

		if (!m_isEnabled || m_moveMode == None || curPoint == m_lastPoint)
		{
			return;
		}

		double deltaX = point.x() - m_lastPoint.x();
		double deltaY = point.y() - m_lastPoint.y();
		double x = 0, y = 0;
		switch (m_moveMode)
		{
		case AllMove:
			if (m_isScreenMap)
			{
				x = deltaX * m_width / m_screenRect.width();
				y = deltaY * m_height / m_screenRect.height();
			}
			else
			{
				x = deltaX / m_pixStep;
				y = deltaY / m_pixStep;
			}
			break;

		case HorMove:
			if (m_isScreenMap)
			{
				y = deltaY * m_height / m_screenRect.height();
			}
			else
			{
				y = deltaY / m_pixStep;
			}
			break;

		case VerMove:
			if (m_isScreenMap)
			{
				x = deltaX * m_width / m_screenRect.width();
			}
			else
			{
				x = deltaX / m_pixStep;
			}
			break;

		default:
			break;
		}
		m_centerPoint = QPointF(m_centerPoint.x() + x, m_centerPoint.y() + y);
		//qDebug() << "zhongxindian" << "x" << x << "y" << y <<m_centerPoint;
		m_centerPoint.setX(qBound(0.0, m_centerPoint.x(), (double)m_width));
		m_centerPoint.setY(qBound(0.0, m_centerPoint.y(), (double)m_height));
		m_lastPoint = point;

		m_valueX = m_centerPoint.x() * (m_xMaxValue - m_xMinValue) / m_width + m_xMinValue;
		m_valueY = (m_height - m_centerPoint.y()) * (m_yMaxValue - m_yMinValue) / m_height + m_yMinValue;

		notifyValueChange();
		updateUI();
	}

	void CrossEQItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
	{
		if (!m_isEnabled || (event->button() != Qt::LeftButton && event->button() != Qt::RightButton))
		{
			return;
		}

		QPointF point = event->pos();
		if (m_centerPath.contains(point))
		{
			m_moveMode = AllMove;
			m_mousePressPoint = point;
			m_lastPoint = point;
		}
		else if (m_horPath.contains(point))
		{
			m_moveMode = HorMove;
			m_mousePressPoint = point;
			m_lastPoint = point;
		}
		else if (m_verPath.contains(point))
		{
			m_moveMode = VerMove;
			m_mousePressPoint = point;
			m_lastPoint = point;
		}
		else
		{
			m_moveMode = None;
		}

		if (event->button() == Qt::RightButton && m_moveMode != None)
		{
			m_isScreenMap = true;
			int x = m_centerPoint.x() * m_screenRect.width() / m_width;
			int y = m_centerPoint.y() * m_screenRect.height() / m_height;
			m_lastPoint = QPointF(x, y);

			QCursor::setPos(QGuiApplication::screens()[QApplication::desktop()->screenNumber(event->screenPos())], x, y);
		}
		else
		{
			m_isScreenMap = false;
		}
	}

	void CrossEQItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
	{
		if (!m_isEnabled)
		{
			return;
		}

		if (event->button() == Qt::RightButton)
		{
			m_isScreenMap = false;
			if (scene() && !scene()->views().isEmpty())
			{
				QPoint globaPos = scene()->views()[0]->mapToGlobal(scene()->views()[0]->mapFromScene(mapToScene(m_centerPoint)));
				QCursor::setPos(QGuiApplication::screens()[QApplication::desktop()->screenNumber(m_lastPoint.toPoint())], globaPos);
			}
		}

		m_moveMode = None;

		emit signalMouseRelease();
	}

	QRectF CrossEQItem::boundingRect()const
	{
		return QRectF(0, 0, m_width, m_height);
	}

	void CrossEQItem::init()
	{
		m_valueX = (m_xMaxValue + m_xMinValue) / 2;
		m_valueY = (m_yMaxValue + m_yMinValue) / 2;
		m_screenRect = QApplication::desktop()->screenGeometry();
		m_screenRect.setWidth(m_screenRect.width() + 1);
		m_screenRect.setHeight(m_screenRect.height() + 1);
		setAcceptHoverEvents(true);
		m_centerPoint = QPointF(m_width / 2, m_height / 2);
		updateUI();
	}

	void CrossEQItem::calPainterPath()
	{
		m_centerPath = QPainterPath();
		m_centerPath.addRect(QRectF(m_centerPoint.rx() - m_centerBlockSize / 2, m_centerPoint.ry() - m_centerBlockSize / 2,
			m_centerBlockSize, m_centerBlockSize));

		m_horPath = QPainterPath();
		m_horPath.addRect(QRectF(0, m_centerPoint.ry() - 4, m_width, 8));

		m_verPath = QPainterPath();
		m_verPath.addRect(QRectF(m_centerPoint.rx() - 4, 0, 8, m_height));
	}

	void CrossEQItem::updateUI()
	{
		calPainterPath();
		update();
	}

	void CrossEQItem::initForm(double newMultiple)
	{
		double multiple = newMultiple / m_multiple;

		if (multiple > 1)
		{
			m_xMinValue *= multiple;
			m_xMaxValue *= multiple;
			m_yMinValue *= multiple;
			m_yMaxValue *= multiple;
			m_valueX *= multiple;
			m_valueY *= multiple;
		}
		else
		{
			m_valueX *= multiple;
			m_valueY *= multiple;
			m_xMinValue *= multiple;
			m_xMaxValue *= multiple;
			m_yMinValue *= multiple;
			m_yMaxValue *= multiple;
		}

		//m_pixStep /= multiple;
		update();

		m_multiple = newMultiple;
	}

	void CrossEQItem::notifyValueChange()
	{
		if (m_lastValueX != m_valueX || m_lastValueY != m_valueY)
		{
			double valueX = QString::number(m_valueX * 1.0 / m_multiple, 'f', m_decimals).toDouble();
			double valueY = QString::number(m_valueY * 1.0 / m_multiple, 'f', m_decimals).toDouble();

			emit signalValueChange(valueX, valueY);
			m_lastValueX = m_valueX;
			m_lastValueY = m_valueY;
		}
	}

}//namespace OfUI 
